﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml.Serialization;

namespace sydfdl.TMS.Tool
{
    /// <summary>
    /// XML帮助类
    /// </summary>
    /// <typeparam name="T">实体类</typeparam>
    public static partial class XmlHelp<T> where T : new()
    {
        /// <summary>
        /// 生成XML
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="obj">实体对象</param>
        public static void WriteFileXML(string path, T obj)
        {
            using (StreamWriter _sw = new StreamWriter(path, false))
            {
                XmlSerializer _xmlS = new XmlSerializer(typeof(T));
                _xmlS.Serialize(_sw, obj);
            }
        }

        /// <summary>
        /// 读取XML
        /// </summary>
        /// <param name="path">路径</param>
        /// <returns>实体</returns>
        public static T ReadFileXML(string path)
        {
            T obj = new T();
            using (TextReader myReader = new StreamReader(path))
            {
                XmlSerializer mySerializer = new XmlSerializer(typeof(T));
                obj = (T)mySerializer.Deserialize(myReader);
            }
            return obj;
        }
    }


    /// <summary>
    /// XML/LINQ帮助类
    /// </summary>
    public static partial class EFHelp
    {
        /// <summary>
        /// LINQ排序
        /// </summary>
        /// <typeparam name="T">实体</typeparam>
        /// <param name="source">数据源</param>
        /// <param name="sortExpression">排序字符</param>
        /// <param name="sortDirection">排序类型ASC/DESC</param>
        /// <returns>数据集合</returns>
        public static IQueryable<T> DataSorting<T>(IQueryable<T> source, string sortExpression, string sortDirection)
        {
            string sortingDir = string.Empty;
            if (sortDirection.ToUpper().Trim() == "ASC")
                sortingDir = "OrderBy";
            else if (sortDirection.ToUpper().Trim() == "DESC")
                sortingDir = "OrderByDescending";
            ParameterExpression param = Expression.Parameter(typeof(T), sortExpression);
            PropertyInfo pi = typeof(T).GetProperty(sortExpression);
            Type[] types = new Type[2];
            types[0] = typeof(T);
            types[1] = pi.PropertyType;
            Expression expr = Expression.Call(typeof(Queryable), sortingDir, types, source.Expression, Expression.Lambda(Expression.Property(param, sortExpression), param));
            IQueryable<T> query = source.AsQueryable().Provider.CreateQuery<T>(expr);
            return query;
        }

        /// <summary>
        /// LINQ分页
        /// </summary>
        /// <typeparam name="T">实体</typeparam>
        /// <param name="source">数据源</param>
        /// <param name="pageNumber">页码</param>
        /// <param name="pageSize">每页数量</param>
        /// <returns>数据集合</returns>
        public static IQueryable<T> DataPaging<T>(IQueryable<T> source, int pageNumber, int pageSize)
        {
            return source.Skip(pageNumber * pageSize).Take(pageSize);
        }

        /// <summary>
        /// 分页并排序
        /// </summary>
        /// <typeparam name="T">返回实体类</typeparam>
        /// <param name="source">数据源</param>
        /// <param name="sortExpression">排序字段</param>
        /// <param name="sortDirection">排序方向</param>
        /// <param name="pageNumber">请求页码</param>
        /// <param name="pageSize">每页条数</param>
        /// <returns>数据集合</returns>
        public static IQueryable<T> SortingAndPaging<T>(IQueryable<T> source, string sortExpression, string sortDirection, int pageNumber, int pageSize)
        {
            IQueryable<T> query = DataSorting<T>(source, sortExpression, sortDirection);
            return DataPaging(query, pageNumber, pageSize);
        }

        /// <summary>
        /// 泛型集合转换为XML、
        /// </summary>
        /// <param name="list">泛型集合</param>
        /// <returns>返回XML</returns>
        public static string GetXML(IEnumerable list, bool IsExpand = false)
        {
            if (list == null)
                return @"<Table />";
            StringBuilder _xml = new StringBuilder();
            _xml.AppendFormat(@"<Table ID=""{0}"" >", list.GetType().GenericTypeArguments[0].Name);
            foreach (string item in GetYiled(list, IsExpand))
            {
                _xml.Append(item);
            }
            _xml.Append(@"</Table>");
            return _xml.ToString();
        }

        /// <summary>
        /// Yiled枚举
        /// </summary>
        /// <param name="_list">数据源</param>
        /// <returns>返回枚举值</returns>
        private static IEnumerable<string> GetYiled(IEnumerable _list, bool IsExpand)
        {
            foreach (var item in _list)
            {
                StringBuilder _inner = new StringBuilder(string.Empty);
                StringBuilder _tempInner = new StringBuilder(string.Empty);
                foreach (PropertyInfo p in item.GetType().GetProperties())
                {
                    if (p.GetGetMethod().IsVirtual)
                        continue;
                    if ((!IsExpand) && p.Name.IndexOf('_') == 0)
                        continue;
                    if (p.GetValue(item, null) is IList)//集合
                    {
                        _tempInner.AppendFormat(@"{0} ", GetXML(p.GetValue(item, null) as IList));
                    }
                    else
                    {
                        if ((p.GetValue(item, null) ?? "").ToString().Contains('<'))//值是XML，这种情况不允许,把值转换为子属性; 因为XML的值不能有<>
                            _tempInner.AppendFormat(@"<Property ID=""{0}"">{1}</Property>", p.Name, p.GetValue(item, null));
                        else
                            _inner.AppendFormat(@" {0}=""{1}""", p.Name, p.GetValue(item, null));
                    }
                }
                if (_inner.ToString().Trim() != string.Empty)
                    yield return string.Format(@"<Row {0} >{1}</Row>", _inner.ToString(), _tempInner.ToString());
            }
        }

    }


    /// <summary>
    /// XML帮助类
    /// </summary>
    /// <typeparam name="T">实体类</typeparam>
    public static partial class EFHelp<T> where T : new()
    {
        /// <summary>
        /// 泛型集合转换为XML、
        /// </summary>
        /// <param name="list">泛型集合</param>
        /// <returns>返回XML</returns>
        public static string GetXML(IEnumerable<T> list, bool IsExpand = false)
        {
            if (list == null)
                return @"<Table />";
            if (new T() is StringBuilder)
            {
                string msg = list.ToList().First().ToString();
                if (!msg.Contains("|"))
                {
                    msg += "|";
                }
                string[] _mes = msg.Split('|');
                return string.Format(@"<Table ID=""{0}"" For=""2""><Row Msg=""{1}"" /></Table>", _mes[1], _mes[0]);
            }
            StringBuilder _xml = new StringBuilder();
            _xml.AppendFormat(@"<Table ID=""{0}"" >", new T().GetType().Name);
            if (list.Count() != 0)
            {
                foreach (string item in GetYiled(list, IsExpand))
                {
                    _xml.Append(item);
                }
            }
            _xml.Append(@"</Table>");
            return _xml.ToString();
        }

        /// <summary>
        /// Yiled枚举
        /// </summary>
        /// <param name="_list">数据源</param>
        /// <returns>返回枚举值</returns>
        private static IEnumerable<string> GetYiled(IEnumerable<T> _list, bool IsExpand)
        {
            foreach (T item in _list)
            {
                StringBuilder _inner = new StringBuilder(string.Empty);
                foreach (PropertyInfo p in typeof(T).GetProperties())
                {
                    if (p.GetGetMethod().IsVirtual)
                        continue;
                    if ((!IsExpand) && p.Name.IndexOf('_') == 0)
                        continue;
                    _inner.AppendFormat(@" {0}=""{1}""", p.Name, p.GetValue(item, null));
                }
                if (_inner.ToString().Trim() != string.Empty)
                    yield return string.Format(@"<Row" + _inner.ToString() + @" />");
            }
        }

        /// <summary>
        /// 生成格式如：<Table ID="T_INFO_Notice"  UserCode=""><Row Action="1" NOTICEID="38" /><Row Action="2" ID="3" /><Row Action="3" ID="3" /></Table>
        /// </summary>
        /// <param name="list">数据源</param>
        /// <returns>XML字符串</returns>
        //public static string GetXML(params U_ParameterAction<T>[] list)
        //{
        //    StringBuilder _xml = new StringBuilder();
        //    var _s = list.Where(a => a != null).Select(b => b);
        //    if (_s.Count() == 0)
        //        return _xml.ToString();
        //    _xml.AppendFormat(@"<Table ID=""{0}"" UserCode=""{1}"" > ", _s.First().ActionTable, _s.First().UserCode);
        //    if (_s.Count() != 0)
        //    {
        //        foreach (var p in _s)
        //        {
        //            foreach (string item in GetYiled(p.AllEntities, p.ActionType))
        //            {
        //                _xml.Append(item);
        //            }
        //        }
        //    }
        //    _xml.Append(@"</Table>");
        //    return _xml.ToString();
        //}

        /// <summary>
        /// Yiled枚举
        /// </summary>
        /// <param name="_list">数据源</param>
        /// <param name="_i">操作类型</param>
        /// <returns>返回枚举值</returns>
        //private static IEnumerable<string> GetYiled(IEnumerable<T> _list, string _i)
        //{
        //    if (_list != null && _list.Count() > 0)
        //    {
        //        foreach (T item in _list)
        //        {
        //            StringBuilder _inner = new StringBuilder(string.Empty);
        //            foreach (PropertyInfo p in typeof(T).GetProperties())
        //            {
        //                if (p.GetGetMethod().IsVirtual)
        //                    continue;
        //                _inner.AppendFormat(@" {0}=""{1}""", p.Name, p.GetValue(item, null));
        //            }
        //            if (_inner.ToString().Trim() != string.Empty)
        //                yield return string.Format(@"<Row Action=""{0}""" + _inner.ToString() + @" />", GetAction(_i));
        //        }
        //    }
        //}

        /// <summary>
        /// 输入字符串，获取操作类型
        /// </summary>
        /// <param name="_i">参数类型</param>
        /// <returns>1为添加；2为删除；3为修改；0为未知</returns>
        //public static byte GetAction(string _i)
        //{
        //    byte _j = 0;
        //    U_ParameterAction<StringBuilder> _list = new U_ParameterAction<StringBuilder>();
        //    if (_i == _list.INSERT)
        //        _j = 1;
        //    else if (_i == _list.UPDATE)
        //        _j = 3;
        //    else if (_i == _list.DELETE)
        //        _j = 2;
        //    return _j;
        //}

        /// <summary>
        /// 输入实体，返回XML
        /// </summary>
        /// <param name="t">实体属性</param>
        /// <returns>XML数据</returns>
        public static string GetXML(T t)
        {
            StringBuilder _xml = new StringBuilder();
            foreach (string item in GetStr(t))
            {
                _xml.Append(item);
            }
            return _xml.ToString();
        }

        /// <summary>
        /// 字符串枚举
        /// </summary>
        /// <param name="t">实体</param>
        /// <returns> 字符串集</returns>
        private static IEnumerable<string> GetStr(T t)
        {
            StringBuilder _inner = new StringBuilder(string.Empty);
            foreach (PropertyInfo p in typeof(T).GetProperties())
            {
                if (p.GetGetMethod().IsVirtual)
                    continue;
                _inner.AppendFormat(@" {0}=""{1}""", p.Name, p.GetValue(t, null));
            }
            if (_inner.ToString().Trim() != string.Empty)
                yield return string.Format(@"<Row Action=""{0}""" + _inner.ToString() + @" />", t.GetType().Name);
        }

        /// <summary>
        /// 输入实体，返回XML（XML序列化器）
        /// </summary>
        /// <param name="t">实体属性</param>
        /// <returns>XML数据</returns>
        public static string XMLSerialize<T>(T entity)
        {
            StringBuilder buffer = new StringBuilder();

            XmlSerializer serializer = new XmlSerializer(typeof(T));
            using (TextWriter writer = new StringWriter(buffer))
            {
                serializer.Serialize(writer, entity);
            }

            return buffer.ToString();

        }

        /// <summary>
        /// 输入实体集合，返回XML（XML序列化器）
        /// </summary>
        /// <param name="t">实体属性</param>
        /// <returns>XML数据</returns>
        public static string XMLSerialize<T>(IEnumerable<T> entities)
        {
            StringBuilder buffer = new StringBuilder();

            XmlSerializer serializer = new XmlSerializer(typeof(IEnumerable<T>));
            using (TextWriter writer = new StringWriter(buffer))
            {
                serializer.Serialize(writer, entities);
            }

            return buffer.ToString();

        }

    }

    /// <summary>
    /// Dictionary转为XML
    /// </summary>
    public static partial class EFHelp
    {
        /// <summary>
        /// 将动态的列生成XML
        /// </summary>
        /// <param name="_data">IEnumerable<Hashtable>源</param>
        /// <param name="_id">行ID</param>
        /// <returns>返回XML</returns>
        public static string GetXML(IEnumerable<Hashtable> _data, string _id)
        {
            StringBuilder _r = new StringBuilder(string.Empty);
            if (_data.Count() == 0)
                return string.Empty;
            _r.Append(@"<data>");
            foreach (var item in _data)
            {
                int i = 1;
                foreach (DictionaryEntry kv in item)
                {
                    _r.AppendFormat(@"<row id=""{0}"" code=""{1}"" value=""{2}"" state=""{3}""  rowid=""{4}"" />",
                        item[_id], kv.Key.ToString(), kv.Value.ToString(), item["_state"], i.ToString());
                    i++;
                }
            }
            _r.Append(@"</data>");
            return _r.ToString();
        }
    }

    /// <summary>
    /// 字符串处理类
    /// </summary>
    public static partial class StringHandling
    {
        #region  判断一个字符串是否是由全数字组成的
        /// <summary>
        /// 判断一个字符串是否是由全数字组成的
        /// </summary>
        /// <param name="value">需要判断的字符串</param>
        /// <returns>如果由全数字组成，返回true；否则返回false</returns>
        static bool IsNumber(string value)
        {
            string express = "^[1-9]*[0-9]*$";
            return ValidateExpress(express, value);
        }

        /// <summary>
        /// 验证一个字符串是否符合指定的正则表达式
        /// </summary>
        /// <param name="express">要匹配的征兆表达式</param>
        /// <param name="value">要验证的字符串</param>
        /// <returns>如果匹配成功，返回true；否则返回false</returns>
        static bool ValidateExpress(string express, string value)
        {
            if (value == null)
                return false;

            Regex regex = new Regex(express);
            if (value.Length == 0)
                return false;

            return regex.IsMatch(value);
        }
        #endregion

        #region 对指定字符串进行MD5加密
        /// <summary>
        /// 对指定字符串进行MD5加密
        /// </summary>
        /// <param name="value">要加密的字符串</param>
        /// <returns>加密后的字符串</returns>
        public static string MD5Encrypt(string value)
        {
            // Create a new instance of the MD5CryptoServiceProvider object.
            using (MD5 md5Hasher = MD5.Create())
            {
                // Convert the input string to a byte array and compute the hash.
                byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(value));

                // Create a new Stringbuilder to collect the bytes
                // and create a string.
                StringBuilder sBuilder = new StringBuilder();

                // Loop through each byte of the hashed data 
                // and format each one as a hexadecimal string.
                for (int i = 0; i < data.Length; i++)
                {
                    sBuilder.Append(data[i].ToString("x2"));
                }

                // Return the hexadecimal string.
                return sBuilder.ToString();
            }
        }
        #endregion

        #region 计算字符串长度（一个汉字长度为2）
        /// <summary>
        /// 计算字符串长度（一个汉字长度为2）
        /// </summary>
        /// <param name="value">要计算的字符串</param>
        /// <returns>字符串的长度</returns>
        public static int StrLength(string value)
        {
            ASCIIEncoding asc = new ASCIIEncoding();
            int result = 0;
            byte[] s = asc.GetBytes(value);
            for (int i = 0; i < s.Length; i++)
            {
                if ((int)s[i] == 63)
                    result += 2;
                else
                    result += 1;
            }
            return result;
        }
        #endregion

        #region  IPv4地址和数字的相互转换
        /// <summary>
        /// 将IPv4地址转化成数字
        /// </summary>
        /// <param name="ip">IPv4格式</param>
        /// <returns>转化后的数字</returns>
        public static int IPtoNumber(string ip)
        {
            int result = 0;
            string[] temp = ip.Split('.');
            int ip1 = Int32.Parse(temp[0]);
            int ip2 = Int32.Parse(temp[1]);
            int ip3 = Int32.Parse(temp[2]);
            int ip4 = Int32.Parse(temp[3]);
            result = ip1 * 256 * 256 * 256 + ip2 * 256 * 256 + ip3 * 256 + ip4;
            return result;
        }

        /// <summary>
        /// 将数字转化成IPv4地址
        /// </summary>
        /// <param name="ip">数字</param>
        /// <returns>转化后的IPv4地址字符串</returns>
        public static string NumbertoIP(int ip)
        {
            string result = "";
            int temp = 0;
            if (ip >= 0)
                temp = ip;
            else
                temp = ip + 1;

            int ip1 = temp / 256 / 256 / 256;
            int ip21 = ip1 * 256 * 256 * 256;
            int ip2 = (temp - ip21) / 256 / 256;
            int ip31 = ip2 * 256 * 256 + ip21;
            int ip3 = (temp - ip31) / 256;
            int ip41 = ip3 * 256 + ip31;
            int ip4 = temp - ip41;

            if (ip < 0)
            {
                ip1 = ip1 + 255;
                ip2 = ip2 + 255;
                ip3 = ip3 + 255;
                ip4 = ip4 + 255;
            }
            result = ip1 + "." + ip2 + "." + ip3 + "." + ip4;
            return result;
        }
        #endregion

        /// <summary>
        /// 验证MD5哈希值
        /// </summary>
        /// <param name="argInput">输入字符串</param>
        /// <param name="argHash">哈希值</param>
        /// <returns>相同返回TRUE,不同返回FALSE</returns>
        public static bool verifyMd5Hash(string argInput, string argHash)
        {
            // Hash the input.
            string hashOfInput = MD5Encrypt(argInput);

            // Create a StringComparer an comare the hashes.
            StringComparer comparer = StringComparer.OrdinalIgnoreCase;

            if (0 == comparer.Compare(hashOfInput, argHash))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }

    /// <summary>
    /// 字符串处理类
    /// </summary>
    public static partial class StringHandling
    {
        /// <summary>
        /// 输入字符串，转换为BASE64的编码
        /// </summary>
        /// <param name="_str">字符串</param>
        /// <returns>BASE64的编码</returns>
        public static string ToBase64String(string _str)
        {
            byte[] bytes = Encoding.Default.GetBytes(_str);
            return Convert.ToBase64String(bytes);
        }

        /// <summary>
        /// 输入BASE64的编码，转换为普通字符串
        /// </summary>
        /// <param name="_str">BASE64的编码</param>
        /// <returns>字符串</returns>
        public static string GetString(string _str)
        {
            byte[] outputb = Convert.FromBase64String(_str);
            return Encoding.Default.GetString(outputb);
        }

        /// <summary>
        /// 根据图片路径返回图片的字节流byte[]
        /// </summary>
        /// <param name="imagePath">图片路径</param>
        /// <returns>返回的字节流</returns>
        public static byte[] getImageByte(string imagePath)
        {
            using (FileStream files = new FileStream(imagePath, FileMode.Open))
            {
                byte[] imgByte = new byte[files.Length];
                files.Read(imgByte, 0, imgByte.Length);
                return imgByte;
            }
        }

        public static void saveImageByte(byte[] image, string imagePath)
        {
            using (MemoryStream _m = new MemoryStream(image))
            {
                using (Image returnImage = Image.FromStream(_m, true))
                {
                    returnImage.Save(imagePath);
                }
            }
        }

        public static string DelImage(string _url)
        {
            try
            {
                if (File.Exists(_url))
                    File.Delete(_url);
                return "";
            }
            catch (Exception f)
            {
                return f.Message;
            }
        }
    }
}
